package wiView.graphics.UI;

import javax.swing.JPanel;
import java.awt.BorderLayout;
import javax.swing.JTabbedPane;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.border.LineBorder;
import java.awt.Color;
import javax.swing.border.TitledBorder;
import javax.swing.UIManager;
import javax.swing.ImageIcon;
import java.awt.Button;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;

import javax.swing.JComboBox;
import javax.swing.JSlider;

import org.graphstream.ui.j2dviewer.J2DGraphRenderer;
import org.graphstream.ui.swingViewer.View;
import org.graphstream.ui.swingViewer.Viewer;

import GraphicComponent.IMediaPanelContainer;

import wiBase.WiException;
import wiBase.WiObject;
import wiBase.baseInterface.OnDrawerListener;
import wiBase.baseObject.Node;
import wiEngine.WiEngine;
import wiEngine.WiEngine.OnEngineControlListener;
import wiView.console.WiObjectOutputStream;
import wiView.graphics.Drawer._Drawer;
import wiView.graphics.GraphObject.WiGraph;
import wiView.graphics.ScenarioMaker.Simulation;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import javax.swing.JPopupMenu;
import java.awt.Component;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.DefaultComboBoxModel;

public class GraphFormPanel extends JPanel implements OnEngineControlListener,IMediaPanelContainer,IViewContainer{
	WiGraph graph;
    ArrayList<String> choseElements = new ArrayList<>();
    String selectedNodeId;
    String selectedPacketId;
    String selectedElement;
    Viewer viewer;
    View view;
    WiEngine wiEngine;
    WiObjectOutputStream output;
    _Drawer drawer;
    protected boolean isPlaying ;
    Simulation sim;
    TableModel listNodeModel ;
	/**
	 * Create the panel.
	 */
	public GraphFormPanel() {
		setBorder(new LineBorder(new Color(0, 0, 0), 1, true));
		setLayout(null);
		
		JPanel panel = new JPanel();
		panel.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), "NetWork", TitledBorder.LEADING, TitledBorder.TOP, null, null));
		panel.setBounds(10, 11, 125, 149);
		add(panel);
		panel.setLayout(null);
		
		JPanel panel_1 = new JPanel();
		panel_1.setLayout(null);
		panel_1.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), "Events", TitledBorder.LEADING, TitledBorder.TOP, null, new Color(0, 0, 0)));
		panel_1.setBounds(10, 171, 125, 368);
		add(panel_1);
		
		JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP);
		tabbedPane.setBounds(145, 11, 795, 528);
		add(tabbedPane);
		
		JPanel visualizerPanel = new JPanel();
		tabbedPane.addTab("Visualizer", null, visualizerPanel, null);
		tabbedPane.setBackgroundAt(0, Color.WHITE);
		visualizerPanel.setLayout(null);
		
		JPanel mediaPanel = new JPanel();
		mediaPanel.setBorder(new LineBorder(Color.BLACK));
		mediaPanel.setBounds(10, 11, 770, 45);
		visualizerPanel.add(mediaPanel);
		mediaPanel.setLayout(null);
		
		JButton btnNewButton_1 = new JButton("Play");
		btnNewButton_1.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				
				if(isPlaying == false){

					isPlaying = true;
					System.out.print("Play");
					Play();
				}
				else{
					
				}
			}
		});
		btnNewButton_1.setBounds(10, 11, 60, 30);
		mediaPanel.add(btnNewButton_1);
		
		JButton btnNewButton_2 = new JButton("Pause");
		btnNewButton_2.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if(isPlaying){
					System.out.print("Pause");
					Pause();
				}
				isPlaying = false;
				
				
			}
		});
		btnNewButton_2.setBounds(80, 11, 60, 30);
		mediaPanel.add(btnNewButton_2);
		
		JButton btnNewButton_3 = new JButton("F.Back");
		btnNewButton_3.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if(isPlaying){
					Backward();
				}
			}
		});
		btnNewButton_3.setBounds(150, 11, 60, 30);
		mediaPanel.add(btnNewButton_3);
		
		JButton btnNewButton_4 = new JButton("F.Next");
		btnNewButton_4.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if(isPlaying){
					Forward();
				}
			}
		});
		btnNewButton_4.setBounds(220, 11, 60, 30);
		mediaPanel.add(btnNewButton_4);
		
		final JComboBox comboBox = new JComboBox();
		comboBox.setModel(new DefaultComboBoxModel(new String[] {"Speed", "1/10", "1/20", "1/50", "1/100", "1/1000"}));
		comboBox.setBounds(290, 11, 96, 30);
		mediaPanel.add(comboBox);
		comboBox.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				// TODO Auto-generated method stub
				System.out.println(comboBox.getSelectedIndex());
				double speed = 0;
				switch(comboBox.getSelectedIndex()){
				case 0:
					speed = 1d;
					break;
				case 1:
					speed = 10d;
					break;
				case 2:
					speed = 20d;
					break;
				case 3:
					speed = 50d;
					break;
				case 4:
					speed = 100d;
					break;
					
				case 5:
					speed = 1000d;
					break;
				default :
					speed = 1;
					break;
				}
				OnSpeedChange(speed);
			}
		});
		JSlider slider = new JSlider();
		slider.setBounds(396, 11, 364, 26);
		mediaPanel.add(slider);
		
		JPanel viewPanel = new JPanel();
		viewPanel.setBorder(new LineBorder(new Color(0, 0, 0)));
		viewPanel.setBounds(10, 67, 770, 322);
		visualizerPanel.add(viewPanel);
		
		JPanel consolePanel = new JPanel();
		consolePanel.setBorder(new TitledBorder(null, "Console", TitledBorder.LEADING, TitledBorder.TOP, null, Color.BLACK));
		consolePanel.setBounds(10, 391, 323, 98);
		visualizerPanel.add(consolePanel);
		
		JPanel propertiesPanel = new JPanel();
		propertiesPanel.setBorder(new TitledBorder(null, "Properties", TitledBorder.LEADING, TitledBorder.TOP, null, Color.BLACK));
		propertiesPanel.setBounds(343, 391, 437, 98);
		visualizerPanel.add(propertiesPanel);
		
		JPanel topologyPanel = new JPanel();
		tabbedPane.addTab("Topology", null, topologyPanel, null);
		
		JPanel nodePanel = new JPanel();
		tabbedPane.addTab("Nodes", null, nodePanel, null);
		
		nodeTables = new JTable();
		nodeTables.setModel(new DefaultTableModel(
			new Object[][] {
			},
			new String[] {
			}
		));
		nodePanel.add(nodeTables);
		
		InitMyComponents();
		view.setSize(viewPanel.getWidth(),viewPanel.getHeight());
		viewPanel.add(view,BorderLayout.CENTER);
		
		JPopupMenu jPopupMenu1 = new JPopupMenu();
		addPopup(viewPanel, jPopupMenu1);
		viewPanel.setLayout(null);
	}
	@Override
	public void onNotification(Object... text) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onTraceFileChange(String traceFile) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onRun(long startTimeSecond, long endTimeSecond) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onPause() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onResume() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onStop() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onSpeedChange(double speed, TimeUnit timeunit) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onBeforeParse() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onAfterParse(long timeParse) {
		// TODO Auto-generated method stub
		drawNodes();
	}

	@Override
	public void onRunTimeChange(long startTimeSecond, long finishTimeSecond) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onUpdateCurrentTime(long startTime9E, long endTime9E,
			long currentTime9E) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public boolean Play() {
        //throw new UnsupportedOperationException("Not supported yet.");
        if (graph.getNodeCount() == 0) {
            System.out.println("Lam gi co node nao ma Mo phong?");
            return false;
        }

        try {
            drawer.Start();
          //  output.setTraceEvent(output);
            sim.Run();

        } catch (Exception ex) {
            System.out.println("???"+ex.getMessage());
            return false;
        }
        return true;
	}

	@Override
	public boolean Stop() {
        try {
            wiEngine.stop();
            Thread.sleep(100);
            drawer.Stop();
            drawNodes();
            return true;
        } catch (Exception ex) {
            return false;
        }
	}

	@Override
	public boolean Pause() {
        //throw new UnsupportedOperationException("Not supported yet.");
        sim.Pause();
       
     //   wiEngine.setStartTime(controlPane.getCurrTime() / (long) 1E3);
        return true;
	}

	@Override
	public boolean Forward() {
        //throw new UnsupportedOperationException("Not supported yet.");
        double speed = wiEngine.getSpeed();
        if (speed > 1 / 10) {
            wiEngine.setSpeed(speed - speed * 0.2, TimeUnit.NANOSECONDS);
            return true;
        } else {
            return false;
        }
	}

	@Override
	public boolean Backward() {
        //throw new UnsupportedOperationException("Not supported yet.");
        double speed = wiEngine.getSpeed();
        if (speed < 1000) {
            wiEngine.setSpeed(speed + speed * 0.2, TimeUnit.NANOSECONDS);
            return true;
        } else {
            return false;
        }
	}

	@Override
	public void SetTimePlay(double time) {
		// TODO Auto-generated method stub
		wiEngine.pause();
        drawer.resetGraph();

        wiEngine.setStartTime((long) time / (long) 1E3);
     //   controlPane.setCurrTime((long) time);
        wiEngine.run();
		
	}
	
	void _Parse() {
        System.out.println("Parsing..");
        try {
            wiEngine.parse();
        } catch (WiException ex) {
            ex.printStackTrace();
            return;
        }
    }
	void OnPlaying() {
    }
//    WiSimConsole cs;
    double speed = 1d;
    private JTable nodeTables;

    void OnSpeedChange(double s) {
        if (s != speed) {
            wiEngine.setSpeed(s, TimeUnit.NANOSECONDS);
            speed = s;
        }
    }
    void StartEngine() {
//      cs = new WiSimConsole(this, null);
//      wiEngine = cs.getEngine();
//      wiEngine.setNative(true);
      wiEngine = WiEngine.getInstance();
      wiEngine.addOnDrawerListener(this.drawer);
    //  output = new WiObjectOutputStream(jScrollPane1, tp_console);
      //output.setTraceEvent(output);
      wiEngine.setStartTime(-1);
      wiEngine.setEndTime(-1);
      wiEngine.addEngineControlListener(this);
     // output.setTraceEvent(output);
  }
    public OnDrawerListener getDrawer() {
        return drawer;
    }
    
    void InitGraph() {
        graph = new WiGraph("g1");
        viewer = new Viewer(graph, Viewer.ThreadingModel.GRAPH_IN_ANOTHER_THREAD);
        viewer.enableAutoLayout();
        view = viewer.addView("v", new J2DGraphRenderer(), false);
        setGraphMouseManager();
    }
    void setGraphMouseManager() {
        ViewMouseManager vmm = new ViewMouseManager(graph, viewer, view);
        vmm.setContainer(this);
    }
    void Start() {
        drawer = new _Drawer(graph);
        StartEngine();
        drawer.setEngine(wiEngine);
        sim = new Simulation(wiEngine, this);
    //    filterFrame = new FilterFrame(sim, this);
    }

    void drawNodes() {
        ArrayList<Integer> nodes = new ArrayList<>();
        for (WiObject n : wiEngine.getListNodes()) {
            Node node = (Node) n;
            nodes.add(node.id);
        }
        DrawNodes(nodes);
    }

    public void DrawNodes(ArrayList<Integer> nodeIds) {
        if (graph.getNodeCount() != 0) {
            graph.clear();
            graph.reset();
            graph.AddAttribute();
            
        }
        view.removeAll();
     //   view.getCamera().resetView();
        
    
        ArrayList<wiBase.baseObject.Node> nodes = new ArrayList<>();
        for (int id : nodeIds) {
            nodes.add(wiEngine.getNode(id));
        }
        drawer.DrawNodes(nodes);
      //  jCheckBoxMenuNodeLabel.setState(true);
    }
    protected void InitMyComponents() {
       // InitMenu();
       // InitControlPanel();
        InitGraph();
       // Layout();

        Start();

    }
    void onFileOpen(String pathFile) {
        if (wiEngine != null) {
            wiEngine.setTraceFile(pathFile);
            _Parse();
        }
//        if(wiEngine != null){
//            wiEngine.setTraceFile(pathFile);
//        }
//        try {
//            _Parse();
//        } catch (Exception ex) {
//            ex.printStackTrace();
//        }
    }
    
    private void doneSelectedViewMenu() {
        System.out.println("doneSelectedViewmenu");
        view.beginSelectionAt(0, 0);
        view.endSelectionAt(0, 0);

    }

	@Override
	public void onRightClick(ArrayList<String> nodes) {
		// TODO Auto-generated method stub
		
	}

    String getPacketId(String spriteId) {
        return spriteId.split("-")[0];
    }

	@Override
	public void onNodeClick(String nodes) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onSpriteClick(String nodes) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onSpriteSelected(String id) {
		// TODO Auto-generated method stub
		
	}
	public void setTraceFile(String traceFile){
		if (wiEngine != null) {
            wiEngine.setTraceFile(traceFile);
            _Parse();
            
        }
		updateTableNodes();
	}
	public void updateTableNodes(){
		/**
		 * Table shows list of nodes and detail
		 * 
		 */
		
	}
	private static void addPopup(Component component, final JPopupMenu popup) {
		component.addMouseListener(new MouseAdapter() {
			public void mousePressed(MouseEvent e) {
				if (e.isPopupTrigger()) {
					showMenu(e);
				}
			}
			public void mouseReleased(MouseEvent e) {
				if (e.isPopupTrigger()) {
					showMenu(e);
				}
			}
			private void showMenu(MouseEvent e) {
				popup.show(e.getComponent(), e.getX(), e.getY());
			}
		});
	}
}
